home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 007 (1987-02-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 007 (1987-02-15)(Ossowski, Stefan)(DE)(PD).adf / C Compiler / gencode.c < prev    next >
C/C++ Source or Header  |  1987-03-04  |  37KB  |  1,075 lines

  1. #include        <stdio.h>
  2. #include        "c.h"
  3. #include        "expr.h"
  4. #include        "gen.h"
  5. #include        "cglbdec.h"
  6.  
  7. /*
  8.  *    68000 C compiler
  9.  *
  10.  *    Copyright 1984, 1985, 1986 Matthew Brandt.
  11.  *    all commercial rights reserved.
  12.  *
  13.  *    This compiler is intended as an instructive tool for personal use. Any
  14.  *    use for profit without the written consent of the author is prohibited.
  15.  *
  16.  *    This compiler may be distributed freely for non-commercial use as long
  17.  *    as this notice stays intact. Please forward any enhancements or questions
  18.  *    to:
  19.  *
  20.  *        Matthew Brandt
  21.  *        Box 920337
  22.  *        Norcross, Ga 30092
  23.  */
  24.  
  25. /*
  26.  *      this module contains all of the code generation routines
  27.  *      for evaluating expressions and conditions.
  28.  */
  29.  
  30. extern struct amode     push[], pop[];
  31.  
  32. struct amode    *gen_expr();            /* forward declaration */
  33.  
  34. struct amode    *make_label(lab)
  35. /*
  36.  *      construct a reference node for an internal label number.
  37.  */
  38. int     lab;
  39. {       struct enode    *lnode;
  40.         struct amode    *ap;
  41.         lnode = xalloc(sizeof(struct enode));
  42.         lnode->nodetype = en_labcon;
  43.         lnode->v.i = lab;
  44.         ap = xalloc(sizeof(struct amode));
  45.         ap->mode = am_direct;
  46.         ap->offset = lnode;
  47.         return ap;
  48. }
  49.  
  50. struct amode    *make_immed(i)
  51. /*
  52.  *      make a node to reference an immediate value i.
  53.  */
  54. int     i;
  55. {       struct amode    *ap;
  56.         struct enode    *ep;
  57.         ep = xalloc(sizeof(struct enode));
  58.         ep->nodetype = en_icon;
  59.         ep->v.i = i;
  60.         ap = xalloc(sizeof(struct amode));
  61.         ap->mode = am_immed;
  62.         ap->offset = ep;
  63.         return ap;
  64. }
  65.  
  66. struct amode    *make_offset(node)
  67. /*
  68.  *      make a direct reference to a node.
  69.  */
  70. struct enode    *node;
  71. {       struct amode    *ap;
  72.         ap = xalloc(sizeof(struct amode));
  73.         ap->mode = am_direct;
  74.         ap->offset = node;
  75.         return ap;
  76. }
  77.         
  78. make_legal(ap,flags,size)
  79. /*
  80.  *      make_legal will coerce the addressing mode in ap1 into a
  81.  *      mode that is satisfactory for the flag word.
  82.  */
  83. struct amode    *ap;
  84. int             flags, size;
  85. {       struct amode    *ap2;
  86.         if( ((flags & F_VOL) == 0) || ap->tempflag )
  87.                 {
  88.                 switch( ap->mode )
  89.                         {
  90.                         case am_immed:
  91.                                 if( flags & F_IMMED )
  92.                                         return;         /* mode ok */
  93.                                 break;
  94.                         case am_areg:
  95.                                 if( flags & F_AREG )
  96.                                         return;
  97.                                 break;
  98.                         case am_dreg:
  99.                                 if( flags & F_DREG )
  100.                                         return;
  101.                                 break;
  102.                         case am_ind:    case am_indx:
  103.                         case am_indx2:  case am_xpc:
  104.                         case am_direct: case am_indx3:
  105.                                 if( flags & F_MEM )
  106.                                         return;
  107.                                 break;
  108.                         }
  109.                 }
  110.         if( flags & F_DREG )
  111.                 {
  112.                 freeop(ap);             /* maybe we can use it... */
  113.                 ap2 = temp_data();      /* allocate to dreg */
  114.                 gen_code(op_move,size,ap,ap2);
  115.                 ap->mode = am_dreg;
  116.                 ap->preg = ap2->preg;
  117.                 ap->deep = ap2->deep;
  118.                 ap->tempflag = 1;
  119.                 return;
  120.                 }
  121.         if( size == 1 )
  122.                 {
  123.                 freeop(ap);
  124.                 ap2 = temp_data();
  125.                 gen_code(op_move,1,ap,ap2);
  126.                 gen_code(op_ext,2,ap2,0);
  127.                 freeop(ap);
  128.                 ap->mode = ap2->mode;
  129.                 ap->preg = ap2->preg;
  130.                 ap->deep = ap2->deep;
  131.                 size = 2;
  132.                 }
  133.         freeop(ap);
  134.         ap2 = temp_addr();
  135.         gen_code(op_move,size,ap,ap2);
  136.         ap->mode = am_areg;
  137.         ap->preg = ap2->preg;
  138.         ap->deep = ap2->deep;
  139.         ap->tempflag = 1;
  140. }
  141.  
  142. do_extend(ap,isize,osize,flags)
  143. /*
  144.  *      if isize is not equal to osize then the operand ap will be
  145.  *      loaded into a register (if not already) and if osize is
  146.  *      greater than isize it will be extended to match.
  147.  */
  148. struct amode    *ap;
  149. int             isize, osize, flags;
  150. {       if( isize == osize )
  151.                 return;
  152.         if( ap->mode != am_areg && ap->mode != am_dreg )
  153.                 make_legal(ap,flags & (F_AREG | F_DREG),isize);
  154.         if( ap->mode == am_areg )
  155.                 return;         /* extend is automagic */
  156.         switch( isize )
  157.                 {
  158.                 case 1:
  159.                         gen_code(op_ext,2,ap,0);
  160.                 case 2:
  161.                         if( osize == 4 )
  162.                                 gen_code(op_ext,4,ap,0);
  163.                 }
  164. }
  165.  
  166. int     isshort(node)
  167. /*
  168.  *      return true if the node passed can be generated as a short
  169.  *      offset.
  170.  */
  171. struct enode    *node;
  172. {       return node->nodetype == en_icon &&
  173.                 (node->v.i >= -65536 && node->v.i <= 65535);
  174. }
  175.  
  176. int     isbyte(node)
  177. /*
  178.  *      return true if the node passed can be evaluated as a byte
  179.  *      offset.
  180.  */
  181. struct enode    *node;
  182. {       return node->nodetype == en_icon &&
  183.                 (-128 <= node->v.i && node->v.i <= 127);
  184. }
  185.  
  186. struct amode    *gen_index(node)
  187. /*
  188.  *      generate code to evaluate an index node (^+) and return
  189.  *      the addressing mode of the result. This routine takes no
  190.  *      flags since it always returns either am_ind or am_indx.
  191.  */
  192. struct enode    *node;
  193. {       struct amode    *ap1, *ap2;
  194.         if( node->v.p[0]->nodetype == en_tempref &&
  195.                 node->v.p[1]->nodetype == en_tempref &&
  196.                 ( node->v.p[0]->v.i >= 8 || node->v.p[1]->v.i >= 8 ))
  197.                 {       /* both nodes are registers, one is address */
  198.                 if( node->v.p[0]->v.i < 8 )
  199.                         {
  200.                         ap1 = gen_expr(node->v.p[1],F_AREG,4);
  201.                         ap1->sreg = node->v.p[0]->v.i;
  202.                         ap1->mode = am_indx2;   /* 0(Ax,Dx) */
  203.                         ap1->offset = makenode(en_icon,0,0);
  204.                         return ap1;
  205.                         }
  206.                 ap1 = gen_expr(node->v.p[0],F_AREG,4);
  207.                 ap2 = gen_expr(node->v.p[1],F_AREG | F_DREG,4);
  208.                 if( ap2->mode == am_dreg )
  209.                         {
  210.                         ap1->mode = am_indx2;
  211.                         ap1->sreg = ap2->preg;
  212.                         }
  213.                 else
  214.                         {
  215.                         ap1->mode = am_indx3;
  216.                         ap1->sreg = ap2->preg;
  217.                         }
  218.                 ap1->offset = makenode(en_icon,0,0);
  219.                 return ap1;
  220.                 }
  221.         ap1 = gen_expr(node->v.p[0],F_AREG | F_IMMED,4);
  222.         if( ap1->mode == am_immed && isshort(ap1->offset) )
  223.                 {
  224.                 ap2 = gen_expr(node->v.p[1],F_AREG,4);
  225.                 ap2->mode = am_indx;
  226.                 ap2->offset = ap1->offset;
  227.                 return ap2;
  228.                 }
  229.         ap2 = gen_expr(node->v.p[1],F_ALL,4);   /* get right op */
  230.         if( ap2->mode == am_immed && isshort(ap2->offset) &&
  231.             ap1->mode == am_areg ) /* make am_indx */
  232.                 {
  233.                 ap2->mode = am_indx;
  234.                 ap2->preg = ap1->preg;
  235.                 ap2->deep = ap1->deep;
  236.                 return ap2;
  237.                 }
  238.         validate(ap1);
  239.         make_legal(ap1,F_AREG | F_VOL,4);
  240.         gen_code(op_add,4,ap2,ap1);             /* add left to address reg */
  241.         ap1->mode = am_ind;             /* make indirect */
  242.         freeop(ap2);                    /* release any temps in ap2 */
  243.         return ap1;                     /* return indirect */
  244. }
  245.  
  246. struct amode    *gen_deref(node,flags,size)
  247. /*
  248.  *      return the addressing mode of a dereferenced node.
  249.  */
  250. struct enode    *node;
  251. int             flags, size;
  252. {       struct amode    *ap1;
  253.         int             siz1;
  254.         switch( node->nodetype )        /* get load size */
  255.                 {
  256.                 case en_b_ref:
  257.                         siz1 = 1;
  258.                         break;
  259.                 case en_w_ref:
  260.                         siz1 = 2;
  261.                         break;
  262.                 case en_l_ref:
  263.                         siz1 = 4;
  264.                         break;
  265.                 }
  266.         if( node->v.p[0]->nodetype == en_add )
  267.                 {
  268.                 ap1 = gen_index(node->v.p[0]);
  269.                 do_extend(ap1,siz1,size,flags);
  270.                 make_legal(ap1,flags,size);
  271.                 return ap1;
  272.                 }
  273.         else if( node->v.p[0]->nodetype == en_autocon )
  274.                 {
  275.                 ap1 = xalloc(sizeof(struct amode));
  276.                 ap1->mode = am_indx;
  277.                 ap1->preg = 6;
  278.                 ap1->offset = makenode(en_icon,node->v.p[0]->v.i);
  279.                 do_extend(ap1,siz1,size,flags);
  280.                 make_legal(ap1,flags,size);
  281.                 return ap1;
  282.                 }
  283.         ap1 = gen_expr(node->v.p[0],F_AREG | F_IMMED,4); /* generate address */
  284.         if( ap1->mode == am_areg )
  285.                 {
  286.                 ap1->mode = am_ind;
  287.                 do_extend(ap1,siz1,size,flags);
  288.                 make_legal(ap1,flags,size);
  289.                 return ap1;
  290.                 }
  291.         ap1->mode = am_direct;
  292.         do_extend(ap1,siz1,size,flags);
  293.         make_legal(ap1,flags,size);
  294.         return ap1;
  295. }
  296.  
  297. struct amode    *gen_unary(node,flags,size,op)
  298. /*
  299.  *      generate code to evaluate a unary minus or complement.
  300.  */
  301. struct enode    *node;
  302. int             flags, size, op;
  303. {       struct amode    *ap;
  304.         ap = gen_expr(node->v.p[0],F_DREG | F_VOL,size);
  305.         gen_code(op,size,ap,0);
  306.         make_legal(ap,flags,size);
  307.         return ap;
  308. }
  309.  
  310. struct amode    *gen_binary(node,flags,size,op)
  311. /*
  312.  *      generate code to evaluate a binary node and return 
  313.  *      the addressing mode of the result.
  314.  */
  315. struct enode    *node;
  316. int             flags, size, op;
  317. {       struct amode    *ap1, *ap2;
  318.         ap1 = gen_expr(node->v.p[0],F_VOL | F_DREG | F_AREG,size);
  319.         ap2 = gen_expr(node->v.p[1],F_ALL,size);
  320.         validate(ap1);          /* in case push occurred */
  321.         gen_code(op,size,ap2,ap1);
  322.         freeop(ap2);
  323.         make_legal(ap1,flags,size);
  324.         return ap1;
  325. }
  326.  
  327. struct amode    *gen_xbin(node,flags,size,op)
  328. /*
  329.  *      generate code to evaluate a restricted binary node and return 
  330.  *      the addressing mode of the result.
  331.  */
  332. struct enode    *node;
  333. int             flags, size, op;
  334. {       struct amode    *ap1, *ap2;
  335.         ap1 = gen_expr(node->v.p[0],F_VOL | F_DREG,size);
  336.         ap2 = gen_expr(node->v.p[1],F_DREG,size);
  337.         validate(ap1);          /* in case push occurred */
  338.         gen_code(op,size,ap2,ap1);
  339.         freeop(ap2);
  340.         make_legal(ap1,flags,size);
  341.         return ap1;
  342. }
  343. struct amode    *gen_shift(node,flags,size,op)
  344. /*
  345.  *      generate code to evaluate a shift node and return the
  346.  *      address mode of the result.
  347.  */
  348. struct enode    *node;
  349. int             flags, size, op;
  350. {       struct amode    *ap1, *ap2;
  351.         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,size);
  352.         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,1);
  353.         validate(ap1);
  354.         gen_code(op,size,ap2,ap1);
  355.         freeop(ap2);
  356.         make_legal(ap1,flags,size);
  357.         return ap1;
  358. }
  359.  
  360. struct amode    *gen_modiv(node,flags,size,op,modflag)
  361. /*
  362.  *      generate code to evaluate a mod operator or a divide
  363.  *      operator. these operations are done on only long
  364.  *      divisors and word dividends so that the 68000 div
  365.  *      instruction can be used.
  366.  */
  367. struct enode    *node;
  368. int             flags, op, size, modflag;
  369. {       struct amode    *ap1, *ap2;
  370.         if( node->v.p[0]->nodetype == en_icon )
  371.                 swap_nodes(node);
  372.         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,4);
  373.         ap2 = gen_expr(node->v.p[1],F_ALL,2);
  374.         validate(ap1);
  375.         gen_code(op,0,ap2,ap1);
  376.         if( modflag )
  377.                 gen_code(op_swap,0,ap1,0);
  378.         gen_code(op_ext,4,ap1,0);
  379.         make_legal(ap1,flags,4);
  380.         freeop(ap2);
  381.         return ap1;
  382. }
  383.  
  384. swap_nodes(node)
  385. /*
  386.  *      exchange the two operands in a node.
  387.  */
  388. struct enode    *node;
  389. {       struct enode    *temp;
  390.         temp = node->v.p[0];
  391.         node->v.p[0] = node->v.p[1];
  392.         node->v.p[1] = temp;
  393. }
  394.  
  395. struct amode    *gen_mul(node,flags,size,op)
  396. /*
  397.  *      generate code to evaluate a multiply node. both operands
  398.  *      are treated as words and the result is long and is always
  399.  *      in a register so that the 68000 mul instruction can be used.
  400.  */
  401. struct enode    *node;
  402. int             flags, size, op;
  403. {       struct amode    *ap1, *ap2;
  404.         if( node->v.p[0]->nodetype == en_icon )
  405.                 swap_nodes(node);
  406.         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,2);
  407.         ap2 = gen_expr(node->v.p[1],F_ALL,2);
  408.         validate(ap1);
  409.         gen_code(op,0,ap2,ap1);
  410.         freeop(ap2);
  411.         make_legal(ap1,flags,4);
  412.         return ap1;
  413. }
  414.  
  415. struct amode    *gen_hook(node,flags,size)
  416. /*
  417.  *      generate code to evaluate a condition operator node (?:)
  418.  */
  419. struct enode    *node;
  420. int             flags, size;
  421. {       struct amode    *ap1, *ap2;
  422.         int             false_label, end_label;
  423.         false_label = nextlabel++;
  424.         end_label = nextlabel++;
  425.         flags = (flags & (F_AREG | F_DREG)) | F_VOL;
  426.         falsejp(node->v.p[0],false_label);
  427.         node = node->v.p[1];
  428.         ap1 = gen_expr(node->v.p[0],flags,size);
  429.         freeop(ap1);
  430.         gen_code(op_bra,0,make_label(end_label),0);
  431.         gen_label(false_label);
  432.         ap2 = gen_expr(node->v.p[1],flags,size);
  433.         if( !equal_address(ap1,ap2) )
  434.                 {
  435.                 freeop(ap2);
  436.                 if( ap1->mode == am_dreg )
  437.                         temp_data();
  438.                 else
  439.                         temp_addr();
  440.                 gen_code(op_move,size,ap2,ap1);
  441.                 }
  442.         gen_label(end_label);
  443.         return ap1;
  444. }
  445.  
  446. struct amode    *gen_asadd(node,flags,size,op)
  447. /*
  448.  *      generate a plus equal or a minus equal node.
  449.  */
  450. struct enode    *node;
  451. int             flags,size,op;
  452. {       struct amode    *ap1, *ap2;
  453.         int             ssize, mask0, mask1;
  454.         ssize = natural_size(node->v.p[0]);
  455.         if( ssize > size )
  456.                 size = ssize;
  457.         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
  458.         ap2 = gen_expr(node->v.p[1],F_DREG | F_AREG | F_IMMED,size);
  459.         validate(ap1);
  460.         gen_code(op,ssize,ap2,ap1);
  461.         freeop(ap2);
  462.         do_extend(ap1,ssize,size);
  463.         make_legal(ap1,flags,size);
  464.         return ap1;
  465. }
  466.  
  467. struct amode    *gen_aslogic(node,flags,size,op)
  468. /*
  469.  *      generate a and equal or a or equal node.
  470.  */
  471. struct enode    *node;
  472. int             flags,size,op;
  473. {       struct amode    *ap1, *ap2, *ap3;
  474.         int             ssize, mask0, mask1;
  475.         ssize = natural_size(node->v.p[0]);
  476.         if( ssize > size )
  477.                 size = ssize;
  478.         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
  479.         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,size);
  480.         validate(ap1);
  481.         if( ap1->mode != am_areg )
  482.                 gen_code(op,ssize,ap2,ap1);
  483.         else
  484.                 {
  485.                 ap3 = temp_data();
  486.                 gen_code(op_move,4,ap1,ap3);
  487.                 gen_code(op,size,ap2,ap3);
  488.                 gen_code(op_move,size,ap3,ap1);
  489.                 freeop(ap3);
  490.                 }
  491.         freeop(ap2);
  492.         do_extend(ap1,ssize,size);
  493.         make_legal(ap1,flags,size);
  494.         return ap1;
  495. }
  496.  
  497. gen_asshift(node,flags,size,op)
  498. /*
  499.  *      generate shift equals operators.
  500.  */
  501. struct enode    *node;
  502. int             flags, size, op;
  503. {       struct amode    *ap1, *ap2, *ap3;
  504.         ap1 = gen_expr(node->v.p[0],F_ALL,size);
  505.         if( ap1->mode != am_dreg )
  506.                 {
  507.                 ap3 = temp_data();
  508.                 gen_code(op_move,size,ap1,ap3);
  509.                 }
  510.         else
  511.                 ap3 = ap1;
  512.         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,size);
  513.         validate(ap3);
  514.         gen_code(op,size,ap2,ap3);
  515.         freeop(ap2);
  516.         if( ap3 != ap1 )
  517.                 {
  518.                 gen_code(op_move,size,ap3,ap1);
  519.                 freeop(ap3);
  520.                 }
  521.         make_legal(ap1,flags,size);
  522.         return ap1;
  523. }
  524.  
  525. struct amode    *gen_asmul(node,flags,size)
  526. /*
  527.  *      generate a *= node.
  528.  */
  529. struct enode    *node;
  530. int             flags, size;
  531. {       struct amode    *ap1, *ap2, *ap3;
  532.         int             siz1;
  533.         siz1 = natural_size(node->v.p[0]);
  534.         ap1 = gen_expr(node->v.p[1],F_DREG | F_VOL,2);
  535.         ap2 = gen_expr(node->v.p[0],F_ALL,siz1);
  536.         if( siz1 == 1 || ap2->mode == am_areg )
  537.                 {
  538.                 ap3 = temp_data();
  539.                 gen_code(op_move,siz1,ap2,ap3);
  540.                 if( siz1 == 1 )
  541.                         gen_code(op_ext,2,ap3,0);
  542.                 freeop(ap3);
  543.                 }
  544.         else
  545.                 ap3 = ap2;
  546.         gen_code(op_muls,0,ap3,ap1);
  547.         gen_code(op_move,siz1,ap1,ap2);
  548.         freeop(ap2);
  549.         return ap1;
  550. }
  551.  
  552. struct amode    *gen_asmodiv(node,flags,size,op)
  553. /*
  554.  *      generate /= and %= nodes.
  555.  */
  556. struct enode    *node;
  557. int             flags, size;
  558. enum e_op op;
  559. {       struct amode    *ap1, *ap2, *ap3;
  560.         int             siz1;
  561.         siz1 = natural_size(node->v.p[0]);
  562.         ap1 = temp_data();
  563.         ap2 = gen_expr(node->v.p[0],F_ALL,siz1);
  564.         validate(ap1);
  565.         gen_code(op_move,siz1,ap2,ap1);
  566.         do_extend(ap1,siz1,4);
  567.         ap3 = gen_expr(node->v.p[1],F_ALL & ~F_AREG,2);
  568.         validate(ap2);
  569.         validate(ap1);
  570.         gen_code(op_divs,0,ap3,ap1);
  571.         freeop(ap3);
  572.         if( op != op_divs )
  573.                 gen_code(op_swap,0,ap1,0);
  574.         gen_code(op_ext,4,ap1,0);
  575.         gen_code(op_move,siz1,ap1,ap2);
  576.         freeop(ap2);
  577.         make_legal(ap1,flags,size);
  578.         return ap1;
  579. }
  580.  
  581. struct amode    *gen_assign(node,flags,size)
  582. /*
  583.  *      generate code for an assignment node. if the size of the
  584.  *      assignment destination is larger than the size passed then
  585.  *      everything below this node will be evaluated with the
  586.  *      assignment size.
  587.  */
  588. struct enode    *node;
  589. int             flags, size;
  590. {       struct amode    *ap1, *ap2;
  591.         int             ssize;
  592.         switch( node->v.p[0]->nodetype )
  593.                 {
  594.                 case en_b_ref:
  595.                         ssize = 1;
  596.                         break;
  597.                 case en_w_ref:
  598.                         ssize = 2;
  599.                         break;
  600.                 case en_l_ref:
  601.                 case en_tempref:
  602.                         ssize = 4;
  603.                         break;
  604.                 }
  605.         if( ssize > size )
  606.                 size = ssize;
  607.         ap2 = gen_expr(node->v.p[1],F_ALL,size);
  608.         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
  609.         validate(ap2);
  610.         gen_code(op_move,ssize,ap2,ap1);
  611.         freeop(ap1);
  612.         return ap2;
  613. }
  614.  
  615. struct amode    *gen_aincdec(node,flags,size,op)
  616. /*
  617.  *      generate an auto increment or decrement node. op should be
  618.  *      either op_add (for increment) or op_sub (for decrement).
  619.  */
  620. struct enode    *node;
  621. int             flags, size;
  622. {       struct amode    *ap1, *ap2;
  623.         int             siz1;
  624.         siz1 = natural_size(node->v.p[0]);
  625.         if( flags & F_NOVALUE )         /* dont need result */
  626.                 {
  627.                 ap1 = gen_expr(node->v.p[0],F_ALL,siz1);
  628.                 gen_code(op,siz1,make_immed(node->v.p[1]),ap1);
  629.                 freeop(ap1);
  630.                 return ap1;
  631.                 }
  632.         if( flags & F_DREG )
  633.                 ap1 = temp_data();
  634.         else
  635.                 ap1 = temp_addr();
  636.         ap2 = gen_expr(node->v.p[0],F_ALL,siz1);
  637.         validate(ap1);
  638.         gen_code(op_move,siz1,ap2,ap1);
  639.         gen_code(op,siz1,make_immed(node->v.p[1]),ap2);
  640.         freeop(ap2);
  641.         do_extend(ap1,siz1,size);
  642.         return ap1;
  643. }
  644.  
  645. push_param(ep)
  646. /*
  647.  *      push the operand expression onto the stack.
  648.  */
  649. struct enode    *ep;
  650. {       struct amode    *ap;
  651.         ap = gen_expr(ep,F_ALL,4);
  652.         gen_code(op_move,4,ap,push);
  653.         freeop(ap);
  654. }
  655.  
  656. int     gen_parms(plist)
  657. /*
  658.  *      push a list of parameters onto the stack and return the
  659.  *      number of parameters pushed.
  660.  */
  661. struct enode    *plist;
  662. {       int     i;
  663.         i = 0;
  664.         while( plist != 0 )
  665.                 {
  666.                 push_param(plist->v.p[0]);
  667.                 plist = plist->v.p[1];
  668.                 ++i;
  669.                 }
  670.         return i;
  671. }
  672.  
  673. struct amode    *gen_fcall(node,flags)
  674. /*
  675.  *      generate a function call node and return the address mode
  676.  *      of the result.
  677.  */
  678. struct enode    *node;
  679. {       struct amode    *ap, *result;
  680.         int             i;
  681.         result = temp_addr();
  682.         temp_addr();                    /* push any used addr temps */
  683.         freeop(result); freeop(result);
  684.         result = temp_data();
  685.         temp_data(); temp_data();       /* push any used data registers */
  686.         freeop(result); freeop(result); freeop(result);
  687.         i = gen_parms(node->v.p[1]);    /* generate parameters */
  688.         if( node->v.p[0]->nodetype == en_nacon )
  689.                 gen_code(op_jsr,0,make_offset(node->v.p[0]),0);
  690.         else
  691.                 {
  692.                 ap = gen_expr(node->v.p[0],F_AREG,4);
  693.                 ap->mode = am_ind;
  694.                 freeop(ap);
  695.                 gen_code(op_jsr,0,ap,0);
  696.                 }
  697.         if( i != 0 )
  698.                 gen_code(op_add,4,make_immed(i * 4),makeareg(7));
  699.         if( flags & F_DREG )
  700.                 result = temp_data();
  701.         else
  702.                 result = temp_addr();
  703.         if( result->preg != 0 || (flags & F_DREG) == 0 )
  704.                 gen_code(op_move,4,makedreg(0),result);
  705.         return result;
  706. }
  707.  
  708. struct amode    *gen_expr(node,flags,size)
  709. /*
  710.  *      general expression evaluation. returns the addressing mode
  711.  *      of the result.
  712.  */
  713. struct enode    *node;
  714. int             flags, size;
  715. {       struct amode    *ap1, *ap2;
  716.         int             lab0, lab1;
  717.         int             natsize;
  718.         if( node == 0 )
  719.                 {
  720.                 printf("DIAG - null node in gen_expr.\n");
  721.                 return 0;
  722.                 }
  723.         switch( node->nodetype )
  724.                 {
  725.                 case en_icon:
  726.                 case en_labcon:
  727.                 case en_nacon:
  728.                         ap1 = xalloc(sizeof(struct amode));
  729.                         ap1->mode = am_immed;
  730.                         ap1->offset = node;
  731.                         make_legal(ap1,flags,size);
  732.                         return ap1;
  733.                 case en_autocon:
  734.                         ap1 = temp_addr();
  735.                         ap2 = xalloc(sizeof(struct amode));
  736.                         ap2->mode = am_indx;
  737.                         ap2->preg = 6;          /* frame pointer */
  738.                         ap2->offset = node;     /* use as constant node */
  739.                         gen_code(op_lea,0,ap2,ap1);
  740.                         make_legal(ap1,flags,size);
  741.                         return ap1;             /* return reg */
  742.                 case en_b_ref:
  743.                 case en_w_ref:
  744.                 case en_l_ref:
  745.                         return gen_deref(node,flags,size);
  746.                 case en_tempref:
  747.                         ap1 = xalloc(sizeof(struct amode));
  748.                         if( node->v.i < 8 )
  749.                                 {
  750.                                 ap1->mode = am_dreg;
  751.                                 ap1->preg = node->v.i;
  752.                                 }
  753.                         else
  754.                                 {
  755.                                 ap1->mode = am_areg;
  756.                                 ap1->preg = node->v.i - 8;
  757.                                 }
  758.                         ap1->tempflag = 0;      /* not a temporary */
  759.                         make_legal(ap1,flags,size);
  760.                         return ap1;
  761.                 case en_uminus:
  762.                         return gen_unary(node,flags,size,op_neg);
  763.                 case en_compl:
  764.                         return gen_unary(node,flags,size,op_not);
  765.                 case en_add:
  766.                         return gen_binary(node,flags,size,op_add);
  767.                 case en_sub:
  768.                         return gen_binary(node,flags,size,op_sub);
  769.                 case en_and:
  770.                         return gen_binary(node,flags,size,op_and);
  771.                 case en_or:
  772.                         return gen_binary(node,flags,size,op_or);
  773.                 case en_xor:
  774.                         return gen_xbin(node,flags,size,op_eor);
  775.                 case en_mul:
  776.                         return gen_mul(node,flags,size,op_muls);
  777.                 case en_umul:
  778.                         return gen_mul(node,flags,size,op_mulu);
  779.                 case en_div:
  780.                         return gen_modiv(node,flags,size,op_divs,0);
  781.                 case en_udiv:
  782.                         return gen_modiv(node,flags,size,op_divu,0);
  783.                 case en_mod:
  784.                         return gen_modiv(node,flags,size,op_divs,1);
  785.                 case en_umod:
  786.                         return gen_modiv(node,flags,size,op_divu,1);
  787.                 case en_lsh:
  788.                         return gen_shift(node,flags,size,op_asl);
  789.                 case en_rsh:
  790.                         return gen_shift(node,flags,size,op_asr);
  791.                 case en_asadd:
  792.                         return gen_asadd(node,flags,size,op_add);
  793.                 case en_assub:
  794.                         return gen_asadd(node,flags,size,op_sub);
  795.                 case en_asand:
  796.                         return gen_aslogic(node,flags,size,op_and);
  797.                 case en_asor:
  798.                         return gen_aslogic(node,flags,size,op_or);
  799.                 case en_aslsh:
  800.                         return gen_asshift(node,flags,size,op_asl);
  801.                 case en_asrsh:
  802.                         return gen_asshift(node,flags,size,op_asr);
  803.                 case en_asmul:
  804.                         return gen_asmul(node,flags,size);
  805.                 case en_asdiv:
  806.                         return gen_asmodiv(node,flags,size,op_divs);
  807.                 case en_asmod:
  808.                         return gen_asmodiv(node,flags,size,op_muls);
  809.                 case en_assign:
  810.                         return gen_assign(node,flags,size);
  811.                 case en_ainc:
  812.                         return gen_aincdec(node,flags,size,op_add);
  813.                 case en_adec:
  814.                         return gen_aincdec(node,flags,size,op_sub);
  815.                 case en_land:   case en_lor:
  816.                 case en_eq:     case en_ne:
  817.                 case en_lt:     case en_le:
  818.                 case en_gt:     case en_ge:
  819.                 case en_ult:    case en_ule:
  820.                 case en_ugt:    case en_uge:
  821.                 case en_not:
  822.                         lab0 = nextlabel++;
  823.                         lab1 = nextlabel++;
  824.                         falsejp(node,lab0);
  825.                         ap1 = temp_data();
  826.                         gen_code(op_moveq,0,make_immed(1),ap1);
  827.                         gen_code(op_bra,0,make_label(lab1),0);
  828.                         gen_label(lab0);
  829.                         gen_code(op_clr,4,ap1,0);
  830.                         gen_label(lab1);
  831.                         return ap1;
  832.                 case en_cond:
  833.                         return gen_hook(node,flags,size);
  834.                 case en_void:
  835.                         natsize = natural_size(node->v.p[0]);
  836.                         freeop(gen_expr(node->v.p[0],F_ALL | F_NOVALUE,natsize));
  837.                         return gen_expr(node->v.p[1],flags,size);
  838.                 case en_fcall:
  839.                         return gen_fcall(node,flags);
  840.                 default:
  841.                         printf("DIAG - uncoded node in gen_expr.\n");
  842.                         return 0;
  843.                 }
  844. }
  845.  
  846. int     natural_size(node)
  847. /*
  848.  *      return the natural evaluation size of a node.
  849.  */
  850. struct enode    *node;
  851. {       int     siz0, siz1;
  852.         if( node == 0 )
  853.                 return 0;
  854.         switch( node->nodetype )
  855.                 {
  856.                 case en_icon:
  857.                         if( -128 <= node->v.i && node->v.i <= 127 )
  858.                                 return 1;
  859.                         if( -32768 <= node->v.i && node->v.i <= 32767 )
  860.                                 return 2;
  861.                         return 4;
  862.                 case en_fcall:  case en_labcon:
  863.                 case en_nacon:  case en_autocon:
  864.                 case en_l_ref:  case en_tempref:
  865.                 case en_cbl:    case en_cwl:
  866.                         return 4;
  867.                 case en_b_ref:
  868.                         return 1;
  869.                 case en_cbw:
  870.                 case en_w_ref:
  871.                         return 2;
  872.                 case en_not:    case en_compl:
  873.                 case en_uminus: case en_assign:
  874.                 case en_ainc:   case en_adec:
  875.                         return natural_size(node->v.p[0]);
  876.                 case en_add:    case en_sub:
  877.                 case en_mul:    case en_div:
  878.                 case en_mod:    case en_and:
  879.                 case en_or:     case en_xor:
  880.                 case en_lsh:    case en_rsh:
  881.                 case en_eq:     case en_ne:
  882.                 case en_lt:     case en_le:
  883.                 case en_gt:     case en_ge:
  884.                 case en_land:   case en_lor:
  885.                 case en_asadd:  case en_assub:
  886.                 case en_asmul:  case en_asdiv:
  887.                 case en_asmod:  case en_asand:
  888.                 case en_asor:   case en_aslsh:
  889.                 case en_asrsh:
  890.                         siz0 = natural_size(node->v.p[0]);
  891.                         siz1 = natural_size(node->v.p[1]);
  892.                         if( siz1 > siz0 )
  893.                                 return siz1;
  894.                         else
  895.                                 return siz0;
  896.                 case en_void:   case en_cond:
  897.                         return natural_size(node->v.p[1]);
  898.                 default:
  899.                         printf("DIAG - natural size error.\n");
  900.                         break;
  901.                 }
  902.         return 0;
  903. }
  904.  
  905. gen_compare(node)
  906. /*
  907.  *      generate code to do a comparison of the two operands of
  908.  *      node.
  909.  */
  910. struct enode    *node;
  911. {       struct amode    *ap1, *ap2;
  912.         int             size;
  913.         size = natural_size(node);
  914.         ap1 = gen_expr(node->v.p[0],F_AREG | F_DREG, size);
  915.         ap2 = gen_expr(node->v.p[1],F_ALL,size);
  916.         validate(ap1);
  917.         gen_code(op_cmp,size,ap2,ap1);
  918.         freeop(ap2);
  919.         freeop(ap1);
  920. }
  921.  
  922. truejp(node,label)
  923. /*
  924.  *      generate a jump to label if the node passed evaluates to
  925.  *      a true condition.
  926.  */
  927. struct enode    *node;
  928. int             label;
  929. {       struct amode    *ap1;
  930.         int             siz1;
  931.         int             lab0;
  932.         if( node == 0 )
  933.                 return;
  934.         switch( node->nodetype )
  935.                 {
  936.                 case en_eq:
  937.                         gen_compare(node);
  938.                         gen_code(op_beq,0,make_label(label),0);
  939.                         break;
  940.                 case en_ne:
  941.                         gen_compare(node);
  942.                         gen_code(op_bne,0,make_label(label),0);
  943.                         break;
  944.                 case en_lt:
  945.                         gen_compare(node);
  946.                         gen_code(op_blt,0,make_label(label),0);
  947.                         break;
  948.                 case en_le:
  949.                         gen_compare(node);
  950.                         gen_code(op_ble,0,make_label(label),0);
  951.                         break;
  952.                 case en_gt:
  953.                         gen_compare(node);
  954.                         gen_code(op_bgt,0,make_label(label),0);
  955.                         break;
  956.                 case en_ge:
  957.                         gen_compare(node);
  958.                         gen_code(op_bge,0,make_label(label),0);
  959.                         break;
  960.                 case en_ult:
  961.                         gen_compare(node);
  962.                         gen_code(op_blo,0,make_label(label),0);
  963.                         break;
  964.                 case en_ule:
  965.                         gen_compare(node);
  966.                         gen_code(op_bls,0,make_label(label),0);
  967.                         break;
  968.                 case en_ugt:
  969.                         gen_compare(node);
  970.                         gen_code(op_bhi,0,make_label(label),0);
  971.                         break;
  972.                 case en_uge:
  973.                         gen_compare(node);
  974.                         gen_code(op_bhs,0,make_label(label),0);
  975.                         break;
  976.                 case en_land:
  977.                         lab0 = nextlabel++;
  978.                         falsejp(node->v.p[0],lab0);
  979.                         truejp(node->v.p[1],label);
  980.                         gen_label(lab0);
  981.                         break;
  982.                 case en_lor:
  983.                         truejp(node->v.p[0],label);
  984.                         truejp(node->v.p[1],label);
  985.                         break;
  986.                 case en_not:
  987.                         falsejp(node->v.p[0],label);
  988.                         break;
  989.                 default:
  990.                         siz1 = natural_size(node);
  991.                         ap1 = gen_expr(node,F_ALL,siz1);
  992.                         gen_code(op_tst,siz1,ap1,0);
  993.                         freeop(ap1);
  994.                         gen_code(op_bne,0,make_label(label),0);
  995.                         break;
  996.                 }
  997. }
  998.  
  999. falsejp(node,label)
  1000. /*
  1001.  *      generate code to execute a jump to label if the expression
  1002.  *      passed is false.
  1003.  */
  1004. struct enode    *node;
  1005. int             label;
  1006. {       struct amode    *ap;
  1007.         int             siz1;
  1008.         int             lab0;
  1009.         if( node == 0 )
  1010.                 return;
  1011.         switch( node->nodetype )
  1012.                 {
  1013.                 case en_eq:
  1014.                         gen_compare(node);
  1015.                         gen_code(op_bne,0,make_label(label),0);
  1016.                         break;
  1017.                 case en_ne:
  1018.                         gen_compare(node);
  1019.                         gen_code(op_beq,0,make_label(label),0);
  1020.                         break;
  1021.                 case en_lt:
  1022.                         gen_compare(node);
  1023.                         gen_code(op_bge,0,make_label(label),0);
  1024.                         break;
  1025.                 case en_le:
  1026.                         gen_compare(node);
  1027.                         gen_code(op_bgt,0,make_label(label),0);
  1028.                         break;
  1029.                 case en_gt:
  1030.                         gen_compare(node);
  1031.                         gen_code(op_ble,0,make_label(label),0);
  1032.                         break;
  1033.                 case en_ge:
  1034.                         gen_compare(node);
  1035.                         gen_code(op_blt,0,make_label(label),0);
  1036.                         break;
  1037.                 case en_ult:
  1038.                         gen_compare(node);
  1039.                         gen_code(op_bhs,0,make_label(label),0);
  1040.                         break;
  1041.                 case en_ule:
  1042.                         gen_compare(node);
  1043.                         gen_code(op_bhi,0,make_label(label),0);
  1044.                         break;
  1045.                 case en_ugt:
  1046.                         gen_compare(node);
  1047.                         gen_code(op_bls,0,make_label(label),0);
  1048.                         break;
  1049.                 case en_uge:
  1050.                         gen_compare(node);
  1051.                         gen_code(op_blo,0,make_label(label),0);
  1052.                         break;
  1053.                 case en_land:
  1054.                         falsejp(node->v.p[0],label);
  1055.                         falsejp(node->v.p[1],label);
  1056.                         break;
  1057.                 case en_lor:
  1058.                         lab0 = nextlabel++;
  1059.                         truejp(node->v.p[0],lab0);
  1060.                         falsejp(node->v.p[1],label);
  1061.                         gen_label(lab0);
  1062.                         break;
  1063.                 case en_not:
  1064.                         truejp(node->v.p[0],label);
  1065.                         break;
  1066.                 default:
  1067.                         siz1 = natural_size(node);
  1068.                         ap = gen_expr(node,F_ALL,siz1);
  1069.                         gen_code(op_tst,siz1,ap,0);
  1070.                         freeop(ap);
  1071.                         gen_code(op_beq,0,make_label(label),0);
  1072.                         break;
  1073.                 }
  1074. }
  1075.